package the.broccoli.platform.service.impl;

import com.alibaba.fastjson.JSON;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.wisteria.framework.util.TextUtils;
import the.broccoli.auth.AbstractShiroAuthService;
import the.broccoli.platform.service.ISessionService;
import the.broccoli.auth.SessionUser;
import the.broccoli.uc.dto.ActionDTO;
import the.broccoli.uc.dto.Secret;
import the.broccoli.uc.entity.User;
import the.broccoli.uc.service.*;
import the.broccoli.uc.service.dto.TokenDTO;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class ShiroAuthService extends AbstractShiroAuthService<SessionUser> implements EnvironmentAware {
    private static final Logger logger = LoggerFactory.getLogger(ShiroAuthService.class);

    @ConditionalOnMissingBean
    @Bean
    public ISessionService sessionService() {
        return ISessionService.Default.getInstance();
    }

    @Autowired
    private IUserService userService;

    @Autowired
    private IUserResService userResService;

    @Autowired
    private ISessionService sessionService;

    @Autowired
    private IUserRoleService userRoleService;

    @Resource
    private ITenantService tenantService;

    @Resource
    private TokenService tokenService;

    @Override
    public void setEnvironment(Environment environment) {

    }

    @Override
    public Set<String> getRoles(SessionUser sessionUser) {
        return userRoleService.getRoleCodeList(sessionUser.getUserId());
    }

    @Override
    public Set<String> getPermissions(SessionUser sessionUser) {
        Set<String> urlSet = null;

        List<ActionDTO> actions = userResService.getActions(sessionUser.getTenantId(), sessionUser.getUserId());
        if (!CollectionUtils.isEmpty(actions)) {
            urlSet = new HashSet<>();

            for (ActionDTO dto : actions) {
                if (StringUtils.hasText(dto.getUrl())) {
                    urlSet.add(dto.getUrl());
                }
            }
        }
        return urlSet;
    }

    @Override
    public SessionUser doLogin(String loginAccount, String password) {
        User user = userService.getByLoginAccount(loginAccount);
        if (user == null) {
            throw new UnknownAccountException();
        }

        if (user.getDisabled() != null && user.getDisabled().intValue() == 1) {
            throw new ExcessiveAttemptsException();
        }

        Secret secret = userService.getByUserId(user.getUserId());
        String md5password = TextUtils.md5(password, secret.getSalt());
        if (!md5password.equals(secret.getPassword())) {
            throw new IncorrectCredentialsException();
        }

        SessionUser sessionUser = new SessionUser();
        sessionUser.setTenantName(tenantService.getTenantNameById(user.getTenantId()));
        sessionUser.setTenantId(user.getTenantId());
        sessionUser.setUserId(user.getUserId());
        sessionUser.setOpenId(user.getOpenId());
        sessionUser.setUserName(user.getUserName());
        sessionUser.setPhone(user.getPhone());
        sessionUser.setAvatar(user.getAvatar());

        TokenDTO tokenDTO = tokenService.newToken(user.getTenantId(), user.getUserId(), JSON.toJSONString(sessionUser));
        if (tokenDTO != null) {
            sessionUser.setToken(String.valueOf(tokenDTO.getToken()));
        }

        sessionService.setSessionData(sessionUser);

        return sessionUser;
    }

    @Override
    public String getLoginUrl() {
        return "/auth/login";
    }

    @Override
    public String[] getWhiteListResources() {
        String[] platformWhiteList = new String[]{
                "/framework/**",
                "/api/**",

                "/",

                "/uc/user/update",
                "/auth/**",
                "/ac/**",

                "/platform/file/**",

                "/setting/file/**",
                "/setting/dict/**",

                "/bu/product/**",
                "/express/**",
                "/delivery/**",
                "/mp/weixin/notify",
                "/niche/**"
                //"/pd/**"
        };
        return platformWhiteList;
    }
}
